﻿using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;

namespace Luka;

/// <summary>
/// 缓存操作类
/// Microsoft.Extensions.Caching.StackExchangeRedis
/// </summary>
public class CacheHandler : ICacheHandler
{
    private readonly IDistributedCache _cache;

    /// <summary>
    /// 构造函数
    /// </summary>
    public CacheHandler(IDistributedCache cache)
    {
        _cache = cache;
    }

    #region 设置缓存

    /// <summary>
    /// 添加缓存
    /// </summary>
    /// <param name="key">键名</param>
    /// <param name="value">值</param>
    /// <param name="minutes">有效时间</param>
    public void SetString(string key, string value, int minutes = 120)
    {
        _cache.SetString(key, value, new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(minutes)
        });
    }

    /// <summary>
    /// 添加缓存(Async)
    /// </summary>
    /// <param name="key">键名</param>
    /// <param name="value">值</param>
    /// <param name="minutes">有效时间（默认120分钟）</param>
    public async Task SetStringAsync(string key, string value, int minutes = 120)
    {
        await _cache.SetStringAsync(key, value, new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(minutes)
        });
    }

    /// <summary>
    /// 添加缓存
    /// </summary>
    /// <param name="key">键名</param>
    /// <param name="value">值</param>
    /// <param name="minutes">有效时间（默认120分钟）</param>
    public void Set<T>(string key, T value, int minutes = 120) where T : class, new()
    {
        _cache.SetString(key, JsonSerializer.Serialize(value), new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(minutes)
        });
    }

    /// <summary>
    /// 添加缓存(Async)
    /// </summary>
    /// <param name="key">键名</param>
    /// <param name="value">值</param>
    /// <param name="minutes">有效时间（默认120分钟）</param>
    public async void SetAsync<T>(string key, T value, int minutes = 120) where T : class, new()
    {
        await _cache.SetStringAsync(key, JsonSerializer.Serialize(value), new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(minutes)
        });
    }

    #endregion 设置缓存

    #region 获取缓存

    /// <summary>
    /// 检查给定 key 是否存在
    /// </summary>
    /// <param name="cacheKey">键</param>
    /// <returns></returns>
    public bool Exists(string cacheKey)
    {
        return _cache.Get(cacheKey) != null;
    }

    /// <summary>
	/// 检查给定 key 是否存在 (Async)
	/// </summary>
	/// <param name="cacheKey">键</param>
	/// <returns></returns>
	public async Task<bool> ExistsAsync(string cacheKey)
    {
        return (await _cache.GetAsync(cacheKey)) != null;
    }

    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="key">键名</param>
    /// <returns></returns>
    public string GetString(string key)
    {
        var cachedData = _cache.GetString(key);
        if (cachedData != null)
        {
            return cachedData;
        }
        return string.Empty;
    }

    /// <summary>
    /// 获取缓存(Async)
    /// </summary>
    /// <param name="key">键名</param>
    /// <returns></returns>
    public async Task<string> GetStringAsync(string key)
    {
        var cachedData = await _cache.GetStringAsync(key);
        if (cachedData != null)
        {
            return cachedData;
        }
        return string.Empty;
    }

    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="key">键名</param>
    /// <returns></returns>
    public T Get<T>(string key) where T : class, new()
    {
        var cachedData = _cache.GetString(key);
        if (cachedData != null)
        {
            return JsonSerializer.Deserialize<T>(cachedData) ?? new T();
        }
        return new T();
    }

    /// <summary>
    /// 获取缓存(Async)
    /// </summary>
    /// <param name="key">键名</param>
    /// <returns></returns>
    public async Task<T> GetAsync<T>(string key) where T : class, new()
    {
        var cachedData = await _cache.GetStringAsync(key);
        if (cachedData != null)
        {
            return JsonSerializer.Deserialize<T>(cachedData) ?? new T();
        }
        return new T();
    }

    #endregion 获取缓存

    #region 删除缓存

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="key">键名</param>
    public void Remove(string key)
    {
        _cache.Remove(key);
    }

    /// <summary>
    /// 删除（Async）
    /// </summary>
    /// <param name="key">键名</param>
    public async void RemoveAsync(string key)
    {
        await _cache.RemoveAsync(key);
    }

    #endregion 删除缓存

    #region 刷新缓存

    /// <summary>
    /// 刷新缓存
    /// </summary>
    /// <param name="key"></param>
    /// <param name="minutes"></param>
    public void Refresh(string key, int minutes = 120)
    {
        var cachedData = _cache.GetString(key);
        if (cachedData != null)
        {
            _cache.SetString(key, cachedData, new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(minutes)
            });
        }
    }

    /// <summary>
    /// 刷新缓存（Async）
    /// </summary>
    /// <param name="key"></param>
    /// <param name="minutes"></param>
    public async void RefreshAsync(string key, int minutes = 120)
    {
        var cachedData = await _cache.GetStringAsync(key);
        if (cachedData != null)
        {
            await _cache.SetStringAsync(key, cachedData, new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(minutes)
            });
        }
    }

    #endregion 刷新缓存
}